// Configurator.cpp: Implementierung der Klasse Configurator.
//
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "lncppapi.h"
#include "Logging.h"
#include "Configurator.h"

Configurator* Configurator::instance = 0;
//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

Configurator::Configurator()
{
	mode=BACKUP; // Default is backup!
	type=FULL;	 // Default is full!	So FULLBACKUP is the default
	
	database=NULL;
	newRepliceID=false;

	overwrite=false; // no default overwrite... is more secure!

	replay=true; // by default you want a replay of the logs!
	wantDateTime=false; // usually we want no replay till one point in time

	backupdirectory[0]='\0'; // make it empty... but has to set by configurator

	alternatedatabase=NULL;
	templates=true;
}

Configurator::~Configurator()
{

}

Configurator* Configurator::GetInstance() 
{
	if (instance==0) {
		instance = new Configurator();
	}

	return instance;
}
void Configurator::RemoveInstance()
{
	if(instance!=0) {
		delete instance;
		instance=0;
	}
}
void Configurator::usage() 
{
	DEBUG("usage() - started!");
	INFO("Usage of this commando:");
	INFO("Syntax: nbackup.exe [parameter]");
	INFO("---------------------------------------------------------------");
	INFO(" -B, --backup (Default)      - Defines a backup!");
	INFO(" -R, --restore               - Defines a restore!");
	INFO(" -F, --fullbackup (Default)  - Defines a fullbackup!");
	INFO(" -I, --incremental           - Defines incremental backup!");
	INFO(" -d, --database DbName       - Define on which database we proceeding!");
	INFO(" -a, --alternate DbName      - Alternate destination database!");
	INFO(" -b, --backdir DirName       - Define which backupdir should be used!");
	INFO(" -r, --generate-replicaid    - Generated new replicid on restore!");
	INFO(" -o, --overwrite             - Overwrite a database on restore!");
	INFO(" -n, --no-replay             - No log-replay on this database!");
	INFO(" --no-templates              - No template backup!");
	INFO(" --date                      - NOT IMPLEMENTED! ");
	INFO(" --time                      - NOT IMPLEMENTED! ");
	INFO(" -v, --verbose               - Set Log Level to Debug!");
	INFO(" --info                      - Set Log Level to Info!");
	INFO(" --warn                      - Set Log Level to Warning!");
	INFO(" --error                     - Set Log Level to Warning!");
	INFO(" -h, --help                  - Displays you this help!");
	DEBUG("usage() - ended!");
}
bool Configurator::ParseCommandLine(int argc, char *argv[]) {
	DEBUG("parseCommandLine(argc,arv[]) - started!");

	int i;
	// go throu all parameters of the commandline
	for (i=1;i<argc;i++) {
		bool hasNext = i+1<argc;

		if (IS_DEBUG()) {
			// Print out parameters
			char format[4096];
			sprintf(format,"argv[%d]=%s",i,argv[i]);
			DEBUG(format);

			if (hasNext) {
				char format[4096];
				sprintf(format,"argv[%d+1]=%s",i,argv[i+1]);
				DEBUG(format);

			}
		} // end - IS_DEBUG()

		// Select mode - Backup are -B or --backup
		if (strcmp(argv[i],"-B")==0 || strcmp(argv[i],"--backup")==0) {
			mode = BACKUP;
			DEBUG("Mode = BACKUP");
		}

		// Select mode - Restore are -R or --restore
		if (strcmp(argv[i],"-R")==0 || strcmp(argv[i],"--restore")==0) {
			mode = RESTORE;
			DEBUG("Mode = RESTORE");
		}

		// Select mode and full - Fullbackup are -F or --fullbackup
		if (strcmp(argv[i],"-F")==0 || strcmp(argv[i],"--fullbackup")==0) {
			mode = BACKUP;
			DEBUG("Mode = BACKUP");
			type = FULL;
			DEBUG("Type = FULL");
		}

		// Select Incremental backup are -I or --incremental
		if (strcmp(argv[i],"-I")==0 || strcmp(argv[i],"--incremental")==0) {
			mode = BACKUP;
			DEBUG("Mode = BACKUP");
			type = INCREMENTAL;
			DEBUG("Type = INCREMENTAL");
		}

		// Set the defined database - -d or --database and for sure has a next entry
		if ((strcmp(argv[i],"-d")==0 || strcmp(argv[i],"--database")==0) && hasNext) {
			type = SINGLE;	// Thats quite sure, that we then want only a single database if we define one
			DEBUG("Type = SINGLE");
			database = argv[i+1];
			i++;
		}

		// Set the defined alternate databasename - -a or --alternate and for sure has a next entry
		if ((strcmp(argv[i],"-a")==0 || strcmp(argv[i],"--alternate")==0) && hasNext) {
			DEBUG("Definition of an alternate database");
			alternatedatabase=argv[i+1];
			i++;
		}

		// Set the backupdirectory (usually it is set by notes.ini) - -b or --backdir and for sure has a next entry
		if ((strcmp(argv[i],"-b")==0 || strcmp(argv[i],"--backdir")==0) && hasNext) {
			DEBUG("Set the backupdirctory by parameter!");
			strcpy(backupdirectory,argv[i+1]);
			i++;
		}

		
		// Generate new ReplicaId
		// Define this if you want restore with another replice ID
		// Options a -r or --generate-replicid
		if (strcmp(argv[i],"-r")==0 || strcmp(argv[i],"--generate-replicid")==0) {
			DEBUG("newRepliceID=true");
			newRepliceID=true;
		}

		// Define this if you didn't want a template backup
		// Option is --no-templates
		if (strcmp(argv[i],"--no-templates")==0) {
			DEBUG("templates=false");
			templates=false;
		}

		// overwrite exisiting file
		// use -o or --overwrite
		if (strcmp(argv[i],"-o")==0 || strcmp(argv[i],"--overwrite")==0) {
			DEBUG("overwrite=true");
			overwrite=true;
		}

		// replay is "on" by default
		// -n = no replay of the logs or --no-replay
		if (strcmp(argv[i],"-n")==0 || strcmp(argv[i],"--no-replay")==0) {
			DEBUG("replay=false");
			replay=false;
		}

		// Help do you want this... we simple return then false!
		if (strcmp(argv[i],"-h")==0 || strcmp(argv[i],"--help")==0 ||
			strcmp(argv[i],"-?")==0 || strcmp(argv[i],"--usage")==0
			) {
			DEBUG("Help wanted!");
			DEBUG("parseCommandLine(argc,arv[]) - ended!");
			return false;
		}

		// To be implemented set point in time
		if (strcmp(argv[i],"--date")==0 && hasNext) {
			// TODO: Write something more usefull 
			ERROR("Set point in Time is not implemented!");
			DEBUG("parseCommandLine(argc,arv[]) - ended!");
			return false;
		}

		// To be implemented set point in time
		if (strcmp(argv[i],"--time")==0 && hasNext) {
			// TODO: Write something more usefull 
			ERROR("Set point in Time is not implemented!");
			DEBUG("parseCommandLine(argc,arv[]) - ended!");
			return false;
		}

		// verbose ?? do you want debug level?
		if (strcmp(argv[i],"-v")==0 || strcmp(argv[i],"--verbose")==0) {
			DEBUG("Active Debuglevel");
			LOGLEVEL(LOG_DEBUG);
		}

		// verbose ?? do you want debug level?
		if (strcmp(argv[i],"-v")==0 || strcmp(argv[i],"--verbose")==0) {
			DEBUG("Active Debuglevel");
			LOGLEVEL(LOG_DEBUG);
		}

		// debug
		if (strcmp(argv[i],"--debug")==0) {
			DEBUG("Active Debuglevel");
			LOGLEVEL(LOG_DEBUG);
		}

		
		// info - this is the default
		if (strcmp(argv[i],"--info")==0) {
			DEBUG("Active Info Loglevel");
			LOGLEVEL(LOG_INFO);
		}

		// warn - Loglevel to warning
		if (strcmp(argv[i],"--warn")==0) {
			DEBUG("Active Warn Loglevel");
			LOGLEVEL(LOG_WARNING);
		}

		// error - Loglevel to error
		if (strcmp(argv[i],"--error")==0) {
			DEBUG("Active Error Loglevel");
			LOGLEVEL(LOG_ERROR);
		}


	}
	DEBUG("parseCommandLine(argc,arv[]) - ended!");
	return true;
}

bool Configurator::ReadConfiguration(LNNotesSession* session) {
	
	try
	{
		LNString sReturn = session->GetEnvironmentString("BACKUP_DIRECTORY");
		if (!sReturn.IsNull()) {
			strcpy(backupdirectory,sReturn);
		}

		// Get Loglevel
		LNString sDebuglevel = session->GetEnvironmentString("BACKUP_DEBUG");
		if (!sDebuglevel.IsNull()) {
			// Define a new debuglevel!
			if (sDebuglevel=="0") {
				LOGLEVEL(LOG_INFO);
			} else {
				LOGLEVEL(LOG_DEBUG);		
			}
		} 


	} catch (LNSTATUS lnerror)
    {
		ERROR("Unhandled Exception thrown! ",lnerror);
		return false;
    }
	
	return true;
}

bool Configurator::IsValid() {
	// first check if we have a defined backupdirectory
	if (backupdirectory[0]=='\0') {
		ERROR("Configuration-Error: No BACKUP_DIRECTORY defined!");
		return false;
	}

	return true;

}